package com.hhq.android_web;

import android.os.Debug;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.hhq.android_web.tools.MyWhat;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;


class Frame{

    long ID;
    long RID;
    int len;
    byte type;
    byte[] datas;


    Frame(byte[] buf  ){
        ID = byte2int(buf,  0, 8);
        RID = byte2int(buf,  8, 8);
        len = (int)byte2int(buf,  16, 4);
        type = (byte)byte2int(buf,  20, 1);
    }
    Frame(long ID, long RID, byte type ){
        this.ID = ID;
        this.RID = RID;
        this.type = type;
        this.len = 0;
    }
    void setLen(int len){
        this.len = len;
    }
    void setDatas(byte[] buf, int start){
        datas = new byte[len];
        System.arraycopy(buf,start, datas, 0, len);
    }

    // ab cd  ->  abcd
    private long byte2int(byte[] dst, int start, int le){
        long res=0;
        int i = 0;
        while( i != le  ){
            res = res << 8;
            int k = dst[start+ i] & 0xff;
            res += k;
            i++;
        }
        return res;
    }
    private void intPutInBytes(long src, byte[] dst, int start, int len){
        while( len > 0  ){
            long k = src & 0xff;
            src = src >> 8;
            dst[ start + len-1  ] = (byte)k;
            len --;
        }
    }
    void pack(byte[] buf){
        intPutInBytes(ID, buf, 0, 8);
        intPutInBytes(RID, buf, 8, 8);
        intPutInBytes(len, buf, 16, 4);
        intPutInBytes(type, buf, 20, 1);
    }
    @Override
    public String toString(){

        return String.format("%x, %x, %x, %x", ID,RID,len,type);
    }


}
 interface Intface {
    public void deal(Frame f);
}

public class App {

    public Handler hand2 =  null;
    public Handler hand1 = null;
    String encoding = "UTF-16";

    public void BeginRecv(  )  {
        try{
            Thread t = new Thread(()->{
                Frame a;
                while(true){
                    try{
//                        System.out.println("HHQ:"+ "等待收一个包");
                        a = recvAFrame();
//                        System.out.println("HHQ:"+ "收到一个包");
                        if( a.len == 0 )
                            break;
                    }catch (Exception e){
                        e.printStackTrace();
                        System.out.println("HHQ:"+ "退出接受线程");
                        break;
                    }
                    // send to main
                    Message ms = new Message();
                    ms.what = MyWhat.MESS_OK;
                    ms.obj = a;
                    hand1.sendMessage(ms);
                }
                hand1.sendEmptyMessage(MyWhat.THREAD_BREAK);  // 2子线程退出了
            }) ;
            t.setDaemon(true);
            t.start();

        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public void close(){
        try {
            ops.close();
            csk.close();
            csk.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public App(String host, int p){
        ip_name = host;
        port = p;
        hand2 = new Handler((message)->{
            if(message.what == MyWhat.MESS_OK ){
                System.out.println("HHQ:子线程曾收到了一个消息");
                String s = (String) message.obj;
                try {
                    new Thread(()->{
                        try {
                            sendAFrame(s);
                        } catch (Exception e) {
                           e.printStackTrace();
                        }
                    }).start();
                } catch (Exception e) {
                    e.printStackTrace();
                    close();
                }
            }
            return false;
        });
    }

    String ip_name = "127.0.0.1";
    int port = 1060;
    Socket csk = null;
    OutputStream ops =  null;
    InputStream ips = null;
    byte[] buf = new byte[8192];
    int  tollen = 0;


    public Frame recvAFrame () throws Exception{

        int len = ips.read(buf, 0, 21);
        if( len != 21 ){
            System.out.println("解包错误1 ! len=" + len);
            return new Frame( 1L, 1L, (byte)0 );
        }
        Frame res  = new Frame(buf);
        if( res.len < 0 ){
            System.out.println("解包错误2 ! len=" + res.len);
            return new Frame( 1L, 1L, (byte)0 );
        }
        len = ips.read(buf, 0, res.len);
        if( res.len != len){
            System.out.println("解包错误3 ! res.len=" + res.len+", len="+len);
            return new Frame( 1L, 1L, (byte)0 );
        }
        res.setDatas(buf, 0);
        return res;
    }

    String getStringFromFrame(Frame res){
        if( res.len < 1 ) return "";
        String outSrt;
        try {
            outSrt = new String(res.datas, 0, res.len, encoding);
        } catch (Exception e) {
            outSrt="";
        }
        return outSrt;
    }

    public void sendAFrame (String data) throws Exception{

        Frame frame = new Frame( (long)1564156, (long)1234256, (byte)1 );

        byte[] arr = data.getBytes(encoding);
        frame.setLen(arr.length);
        int tollen = 21 + frame.len;

        frame.pack(buf);

        // for(  int i=0; i<21; i++)
        //     System.out.printf("%x ", buf[i]);
        // System.out.println();

        System.arraycopy(arr,0,buf,21, frame.len);

        // for(  int i=0; i<tollen; i++)
        //     System.out.printf("%x ", buf[21+i]);
        // System.out.println();
        ops.write(buf, 0, tollen);
    }

    public boolean start ()  {

        try{
            InetAddress inetAddress = InetAddress.getByName(ip_name);

            csk = new Socket(inetAddress, port);

            System.out.println("开始连接：" + inetAddress.getHostAddress() );

            ops =  csk.getOutputStream();
            ips = csk.getInputStream();
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

}